﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;
using Sector7.Medical.EntityType;
using Sector7.Medical.DAO.Standard;
using Sector7.Framework.DB;
using Sector7.Framework.Core;
using Sector7.Framework.Enums;
using Sector7.Medical.Consts;
using Sector7.Framework.Utility;
using Sector7.Medical.Enums;

namespace Sector7.Medical.Services
{
    // 注意: 使用“重构”菜单上的“重命名”命令，可以同时更改代码和配置文件中的类名“StockService”。
    public class StockService : IStockService
    {
        public int AddChargeRecord(long billId, DateTime recordTime, decimal amount, int deptId, int paymentType)
        {
            var record = new M7_ChargeRecord();

            record.BillId = billId;
            record.DeptId = deptId;
            record.RecordTime = recordTime;
            record.Amount = amount;
            record.BillType = Convert.ToInt32(billId.ToString().Substring(8, 3));
            record.PaymentType = paymentType;
            record.IsValid = true;
            if (record.BillType == C_BillType.ADJUST_RECORD)
            {
                record.Remarks = "调价盈亏";
            }

            object result = DAOFactory.GetDAO<ChargeRecordDAO>().Create(record);
            return Convert.ToInt32(result);
        }

        public int AddPurchasesBill(M7_PurchasesBill bill)
        {
            bill.RecordTime = DateTime.Now;

            // 1. 保存采购记录
            DAOFactory.GetDAO<PurchasesBillDAO>().Create(bill);
            DAOFactory.GetDAO<PurchasesBillItemDAO>().Create(bill.Items);

            // 2. 保存费用记录
            AddChargeRecord(bill.BillId, bill.RecordTime, -bill.PayAmount, bill.DeptId, bill.PaymentType);

            // 3. 更新库存 & 自动调价
            foreach (var item in bill.Items)
            {
                // 3.1 创建条件
                var cond1 = new EntityConditionBase(C_ColumnName.DRUG_ID, item.DrugId);
                var cond2 = new EntityConditionBase(C_ColumnName.BATCH_NUMBER, item.BatchNumber);
                var cond3 = new EntityConditionBase(C_ColumnName.LOT_NUMBER, item.LotNumber);
                var cond4 = new EntityConditionBase(C_ColumnName.SPEC_ID, item.SpecId);
                var cond5 = new EntityConditionBase(C_ColumnName.UNIT_ID, item.UnitId);

                // 3.2 更新库存
                M7_DrugStock stock = null;
                var stockList = DAOFactory.GetDAO<DrugStockDAO>().ReadAll(cond1, cond2, cond3, cond4, cond5);
                if (stockList.Count == 1)
                {
                    stock = stockList[0];

                    var delta = ClientUtil.CreateDelta(typeof(M7_DrugStock));
                    delta.Conditions.Add(C_ColumnName.STOCK_ID, stock.StockId);
                    delta.DeltaProperties.Add(C_ColumnName.NUMBER, stock.Number + item.Number);

                    DAOFactory.GetDAO<DrugStockDAO>().Update(delta);
                }
                else
                {
                    stock = new M7_DrugStock();
                    stock.DrugId = item.DrugId;
                    stock.BatchNumber = item.BatchNumber;
                    stock.LotNumber = item.LotNumber;
                    stock.SpecId = item.SpecId;
                    stock.UnitId = item.UnitId;
                    stock.Number = item.Number;
                    stock.ProducedDate = item.ProducedDate;
                    stock.AvailableDate = item.AvailableDate;
                    stock.IsOverdue = false;

                    DAOFactory.GetDAO<DrugStockDAO>().Create(stock);
                }

                // 3.3 自动调价
                M7_DrugPrice price = null;
                var priceList = DAOFactory.GetDAO<DrugPriceDAO>().ReadAll(cond1, cond4, cond5);
                if (priceList.Count == 1)
                {
                    price = priceList[0];

                    decimal currPrice_P = price.PurchasesPrice;
                    decimal currPrice_S = price.SalesPrice;
                    decimal newPrice_P = item.PurchasesPrice;
                    decimal newPrice_S = item.SalesPrice;
                    decimal number = stock.Number + item.Number;

                    if (currPrice_P != newPrice_P)
                    {
                        newPrice_P = (stock.Number * currPrice_P + item.Number * newPrice_P) / number;
                    }
                    if (currPrice_S != newPrice_S)
                    {
                        newPrice_S = (stock.Number * currPrice_S + item.Number * newPrice_S) / number;
                    }

                    if (currPrice_P != newPrice_P || currPrice_S != newPrice_S)
                    {
                        var delta = ClientUtil.CreateDelta(typeof(M7_DrugPrice));
                        delta.Conditions.Add(C_ColumnName.PRICE_ID, price.PriceId);
                        delta.DeltaProperties.Add(C_ColumnName.PURCHASES_PRICE, newPrice_P);
                        delta.DeltaProperties.Add(C_ColumnName.SALES_PRICE, newPrice_S);

                        DAOFactory.GetDAO<DrugPriceDAO>().Update(delta);
                    }
                }
                else
                {
                    price = new M7_DrugPrice();

                    price.DrugId = item.DrugId;
                    price.UnitId = item.UnitId;
                    price.PurchasesPrice = item.PurchasesPrice;
                    price.SalesPrice = item.SalesPrice;
                    price.SpecId = item.SpecId;

                    DAOFactory.GetDAO<DrugPriceDAO>().Create(price);
                }
            }

            return 1;
        }

        public List<M7_Drug> GetDrugListByKeywordsAndProperties(string keywords, DrugPropertyType properties)
        {
            return DAOFactory.GetDAO<DrugDAO>().ReadAll(keywords, properties);
        }

        /// <summary>
        /// 添加药房发药记录
        /// </summary>
        /// <param name="dispenseBill"></param>
        /// <returns></returns>
        public int AddDispenseBill(M7_DispenseBill dispenseBill)
        {
            int ret = 0;

            object result = DAOFactory.GetDAO<DispenseBillDAO>().Create(dispenseBill);
            ret = Convert.ToInt32(result);
            if (ret == 1)
            {
                List<M7_Recipe> recipeList = dispenseBill.RecipeList;
                if (recipeList != null && recipeList.Count != 0)
                {
                    foreach (M7_Recipe recipe in recipeList)
                    {
                        recipe.Status = C_BillStatus.COMPLETED;

                        var delta = ClientUtil.CreateDelta(typeof(M7_Recipe));
                        delta.Conditions.Add(C_ColumnName.RECIPE_ID, recipe.RecipeId);
                        delta.DeltaProperties.Add(C_ColumnName.RECORD_STATUS, C_BillStatus.COMPLETED);
                        ret = DAOFactory.GetDAO<RecipeDAO>().Update(delta);
                    }

                    if (dispenseBill.MedicalRecordList != null && dispenseBill.MedicalRecordList.Count != 0)
                    {
                        for (int i = 0; i < dispenseBill.MedicalRecordList.Count; i++)
                        {
                            M7_MedicalRecord medicalRecord = dispenseBill.MedicalRecordList[i];
                            medicalRecord.Status = C_BillStatus.COMPLETED;

                            var delta = ClientUtil.CreateDelta(typeof(M7_MedicalRecord));
                            delta.Conditions.Add(C_PrimaryKeyName.MEDICAL_RECORD_ID, medicalRecord.EmrId);
                            delta.DeltaProperties.Add(C_ColumnName.MEDICAL_RECORD_STATUS, C_BillStatus.COMPLETED);
                            ret = DAOFactory.GetDAO<RecipeDAO>().Update(delta);
                        }
                    }
                }
            }

            return ret;
        }

        public long AddDrugSpec(M7_DrugSpec drugSpec)
        {
            object ret = DAOFactory.GetDAO<DrugSpecDAO>().Create(drugSpec);
            return Convert.ToInt64(ret);
        }

        public List<M7_Drug> GetDrugListWithPriceByKeywords(string keywords)
        {
            return DAOFactory.GetDAO<DrugDAO>().ReadDrugsWithPrice(keywords);
        }

        public int AddAdjustRecord(M7_AdjustRecord record)
        {
            record.RecordTime = DateTime.Now;

            // 1. 保存调价记录
            DAOFactory.GetDAO<AdjustRecordDAO>().Create(record);
            DAOFactory.GetDAO<AdjustRecordItemDAO>().CreateAll(record.Items);

            foreach (var item in record.Items)
            {
                // 2. 获取现有价格
                var price = DAOFactory.GetDAO<DrugPriceDAO>().Read(item.DrugId, item.SpecId, item.UnitId);

                // 2.1. 更新价格
                var delta = new EntityDeltaBase(typeof(M7_DrugPrice));
                delta.Conditions.Add(C_ColumnName.PRICE_ID, price.PriceId);
                delta.DeltaProperties.Add(C_ColumnName.PURCHASES_PRICE, item.NewPurchasesPrice);
                delta.DeltaProperties.Add(C_ColumnName.SALES_PRICE, item.NewSalesPrice);

                DAOFactory.GetDAO<DrugPriceDAO>().Update(delta);

                // 2.2. 记录盈亏（默认价格单位对应包装单位进行计算）
                decimal priceSpread_P = item.NewPurchasesPrice - item.OldPurchasesPrice;
                decimal priceSpread_S = item.NewSalesPrice - item.OldSalesPrice;
                decimal spread = 0;

                var usageStock = DAOFactory.GetDAO<DrugStockDAO>().Read(price.DrugId, price.SpecId, price.Spec.UsageUnitId);
                if (usageStock != null && usageStock.Number > 0)
                {
                    spread -= (priceSpread_P / price.Spec.PackSpec) * usageStock.Number;
                    spread += (priceSpread_S / price.Spec.PackSpec) * usageStock.Number;
                }

                var packStock = DAOFactory.GetDAO<DrugStockDAO>().Read(price.DrugId, price.SpecId, price.Spec.PackUnitId);
                if (packStock != null && packStock.Number > 0)
                {
                    spread -= priceSpread_P * packStock.Number;
                    spread += priceSpread_S * packStock.Number;
                }

                var stockStock = DAOFactory.GetDAO<DrugStockDAO>().Read(price.DrugId, price.SpecId, price.Spec.StockUnitId);
                if (stockStock != null && stockStock.Number > 0)
                {
                    spread -= (priceSpread_P * price.Spec.StockSpec) * stockStock.Number;
                    spread += (priceSpread_S * price.Spec.StockSpec) * stockStock.Number;
                }

                if (spread != 0)
                {
                    AddChargeRecord(record.RecordId, record.RecordTime, spread, record.DeptId, C_PaymentType.UNKNOWN);
                }
            }

            return 1;
        }
    }
}
